﻿using Microsoft.EntityFrameworkCore;
using Vinno.WMS.Pack.Core.Entities;

namespace Vinno.WMS.Pack.Core
{
    public partial class WmsService
    {
        /// <summary>
        /// 获取 实体仓储对象
        /// </summary>
        private MaterialInStorageStore MaterialInStorageStore => ServiceProvider.GetService<MaterialInStorageStore>();

        /// <summary>
        /// 获取 实体查询数据集
        /// </summary>
        public IQueryable<MaterialInStorage> MaterialInStorages => MaterialInStorageStore.Entities;

        /// <summary>
        /// 根据编号查找
        /// </summary>
        /// <param name="id">数据实体编号</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult<MaterialInStorageOutputDto>> FindMaterialInStorageById(Guid id)
        {
            Check.NotEmpty(id, nameof(id));

            var outputDto = MaterialInStorages.Where(o => o.Id.Equals(id)).ToOutput<MaterialInStorage, MaterialInStorageOutputDto>().FirstOrDefault();
            if (outputDto != null)
            {
                return await Task.FromResult(new OperationResult<MaterialInStorageOutputDto>(OperationResultType.Success, "OK", outputDto));
            }

            return await Task.FromResult(new OperationResult<MaterialInStorageOutputDto>(OperationResultType.NotFound, "Not Found", outputDto));
        }

        /// <summary>
        /// 新增入库记录
        /// </summary>
        /// <param name="dto">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> CreateMaterialInStorage(MaterialInStorageInputDto dto)
        {
            Check.NotNull(dto, nameof(dto));

            OperationResult operation = OperationResult.Error("操作尚未处理");
            #region step1:WareHouseAreaPosId => WareHouseId,WareHouseAreaId, WareHouseAreaPosId                        
            var wareHouseIds = WareHouseAreaPosStore.Entities.Where(a => a.Id == dto.WareHouseAreaPosId)
                .Select(a => new
                {
                    WareHouseAreaPosId = a.Id,
                    WareHouseAreaId = a.WareHouseArea.Id,
                    WareHouseId = a.WareHouseArea.WareHouse.Id
                }).FirstOrDefault();
            if (wareHouseIds == null) return OperationResult.Error("库位不存在");
            #endregion

            #region step2:物料仓库信息            
            Material material = MaterialStore.Entities.FirstOrDefault(a =>
            a.WareHouseAreaPosId == wareHouseIds.WareHouseAreaPosId &&
            a.WareHouseAreaId == wareHouseIds.WareHouseAreaId &&
            a.WareHouseId == wareHouseIds.WareHouseId &&
            a.IPNId == dto.IPNId);
            if (material == null)
            {
                material = new Material
                {
                    IPNId = dto.IPNId,
                    WareHouseId = wareHouseIds.WareHouseId,
                    WareHouseAreaId = wareHouseIds.WareHouseAreaId,
                    WareHouseAreaPosId = wareHouseIds.WareHouseAreaPosId
                };
                operation = await MaterialStore.InsertAsync(material);
                if (operation.Failed) return operation;
            }

            #endregion

            #region step3:新增入库记录
            MaterialInStorage inStorage = new MaterialInStorage
            {
                MaterialId = material.Id,
                Project = dto.Project,
                Num = dto.Num,
                OrderNo = dto.OrderNo,
                Remark = dto.Remark,
                HandleStatus = dto.HandleStatus,
            };
            operation = await MaterialInStorageStore.InsertAsync(inStorage);
            if (operation.Failed) return operation;

            #endregion

            #region step4:物料仓库数量处理
            material.Num += inStorage.Num;
            operation = await MaterialStore.UpdateAsync(material);
            
            #endregion

            return operation;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="dto">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> UpdateMaterialInStorage(MaterialInStorageInputDto dto)
        {
            Check.NotNull(dto, nameof(dto));

            OperationResult operation = OperationResult.Error("操作尚未处理");
            #region step1:WareHouseAreaPosId => WareHouseId,WareHouseAreaId, WareHouseAreaPosId                        
            var wareHouseIds = WareHouseAreaPosStore.Entities.Where(a => a.Id == dto.WareHouseAreaPosId)
                .Select(a => new
                {
                    WareHouseAreaPosId = a.Id,
                    WareHouseAreaId = a.WareHouseArea.Id,
                    WareHouseId = a.WareHouseArea.WareHouse.Id
                }).FirstOrDefault();
            if (wareHouseIds == null) return OperationResult.Error("库位不存在");
            #endregion

            #region step2:物料仓库信息            
            Material material = MaterialStore.Entities.FirstOrDefault(a =>
            a.WareHouseAreaPosId == wareHouseIds.WareHouseAreaPosId &&
            a.WareHouseAreaId == wareHouseIds.WareHouseAreaId &&
            a.WareHouseId == wareHouseIds.WareHouseId &&
            a.IPNId == dto.IPNId);
            if (material == null)
            {
                operation = await MaterialStore.InsertAsync(new Material
                {
                    IPNId = dto.IPNId,
                    Num = dto.Num,
                    WareHouseId = wareHouseIds.WareHouseId,
                    WareHouseAreaId = wareHouseIds.WareHouseAreaId,
                    WareHouseAreaPosId = wareHouseIds.WareHouseAreaPosId
                });
            }
            if (operation.Failed) return operation;

            #endregion

            #region step3:新增入库记录
            MaterialInStorage inStorage = new MaterialInStorage
            {
                MaterialId = material.Id,
                Project = dto.Project,
                Num = dto.Num,
                OrderNo = dto.OrderNo,
                Remark = dto.Remark,
                HandleStatus = dto.HandleStatus,
            };
            operation = await MaterialInStorageStore.InsertAsync(inStorage);
            if (operation.Failed) return operation;

            #endregion

            #region step4:物料仓库数量处理
            material.Num += inStorage.Num;
            operation = await MaterialStore.UpdateAsync(material);

            #endregion

            return operation;
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> CreateMaterialInStorages(params MaterialInStorageInputDto[] dtos)
        {
            return await MaterialInStorageStore.InsertByDtoAsync(dtos);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> UpdateMaterialInStorages(params MaterialInStorageInputDto[] dtos)
        {
            return await MaterialInStorageStore.UpdateByDtoAsync(dtos);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="id">数据实体编号</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> DeleteMaterialInStorage(Guid id)
        {
            OperationResult operation = OperationResult.Error("撤销失败");
            var instorage = MaterialInStorageStore.Entities.FirstOrDefault(a => a.Id == id);
            Check.NotNull(instorage, nameof(instorage));

            var material = MaterialStore.Entities.FirstOrDefault(a => a.Id == instorage.MaterialId);
            Check.NotNull(material, nameof(material));
            if (material.Num < material.Num) return OperationResult.Error("库存不足，撤销失败");

            material.Num -= instorage.Num;
            operation = MaterialStore.Update(material);
            //if (material.Num > 0)
            //{
            //    operation = MaterialStore.Update(material);
            //}
            //else
            //{
            //    operation = MaterialStore.Delete(material);
            //}

            if (operation.Succeeded)
            {
                operation = MaterialInStorageStore.Delete(instorage);
            }
            return operation;
        }

    }
}